﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.CodeDom.Compiler;
using ViewMaker.Core;
using ViewMaker.Core.Controls;
using System.Windows.Media;
using System.ComponentModel.DataAnnotations;

namespace ViewMaker.SampleApplication
{
    [View(ViewControlType.Grid)]
    [ViewProperty(GridViewControl.Properties.HeaderPosition, LayoutHeaderPosition.Top)]
    [ViewProperty(GridViewControl.Properties.ItemColumnSize, 2)]
    [ViewProperty(GridViewControl.Properties.HeaderFontSize, 16.0)]
    [ViewProperty(GridViewControl.Properties.HeaderHeight, 30)]
    [ViewProperty(GridViewControl.Properties.HeaderForeground, "White")]
    [ViewProperty(GridViewControl.Properties.HeaderBackground, "Blue")]
    public class OnlineViewMaker : ViewModelBase
    {
        [Display(Name = "Step1. Write your ViewModel code.")]
        [View(ViewControlType.TextBox)]
        [ViewProperty(TextBoxViewControl.Properties.IsMultiline, true)]
        [ViewProperty(TextBoxViewControl.Properties.GridHeight, "5*")]
        [ViewProperty("AcceptsTab", true)]
        [ViewProperty(TextBoxViewControl.Properties.VerticalAlignment, LayoutVerticalAlignment.Top)]
        public string CodeString { get; set; }

        [Display(Name = "Step2. Build your ViewModel code.")]
        [ViewProperty(ButtonViewControl.Properties.FontSize, 16.0)]
        [ViewProperty(ButtonViewControl.Properties.Foreground, "White")]
        [ViewProperty(ButtonViewControl.Properties.Background, "Blue")]
        public ICommand Build { get { return CreateCommand(BuildAction); } }

        [Display(Name = "Step3. Edit generated View by Layout Editor.",Description="Let's right click on the window and select 'Edit Layout' , the Layout Editor is displayed.")]
        [View(ViewControlType.Literal)]
        [ViewProperty(LiteralViewControl.Properties.Literal, @"<ContentControl Content=""{Binding Path=Contents, Mode=OneWay}"" />")]
        [ViewProperty(TextBoxViewControl.Properties.GridHeight, "5*")]
        [ViewProperty(TextBoxViewControl.Properties.VerticalAlignment, LayoutVerticalAlignment.Top)]
        public object Contents
        {
            get { return _contents; }
            set { _contents = value; OnPropertyChanged("Contents"); }
        }
        private object _contents;

        public OnlineViewMaker()
        {
            CodeString = @"
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Windows.Input;
using ViewMaker;
using ViewMaker.Core.Controls;
using ViewMaker.Core.Utils;

namespace OnlineViewModels
{
    public class TestClass : ViewModel
    {
        public string Input { get; set; }

        public string Output
        {
            get { return _output; }
            set { _output = value; OnPropertyChanged(""Output""); }
        }
        private string _output;

        public ICommand Exec { get { return CreateCommand(() => Output = Input); } }
    }
}
";
        }

        private void BuildAction()
        {
            var cp = new Microsoft.CSharp.CSharpCodeProvider();//new Dictionary<string, string> { { "CompilerVersion", "v4.0" } });
            var cps = new CompilerParameters();
            cps.GenerateInMemory = true;
            cps.GenerateExecutable = false;
            cps.IncludeDebugInformation = true;

            cps.ReferencedAssemblies.Add("System.dll");
            string path = typeof(ICommand).Assembly.Location;
            cps.ReferencedAssemblies.Add(path);
            cps.ReferencedAssemblies.Add("System.ComponentModel.DataAnnotations.dll");
            cps.ReferencedAssemblies.Add("System.Xml.Linq.dll");
            cps.ReferencedAssemblies.Add("System.Xml.dll");
            path = typeof(ViewUtil).Assembly.Location;
            cps.ReferencedAssemblies.Add(path);
            try
            {
                var result = cp.CompileAssemblyFromSource(cps, CodeString);
                if (result.Errors.Count > 0)
                {
                    string errorString = "";
                    foreach (CompilerError err in result.Errors)
                    {
                        errorString += err.ToString() + Environment.NewLine;
                    }
                    this.ShowMessage(errorString, "Error");
                }
                else
                {
                    foreach (var viewModelType in result.CompiledAssembly.GetTypes())
                    {
                        var ctor = viewModelType.GetConstructor(new Type[] { });
                        if (ctor != null)
                        {
                            Contents = ViewUtil.BuildContent(Activator.CreateInstance(viewModelType));
                            break;
                        }
                    }
                }

            }
            catch (Exception ex)
            {
                this.ShowMessage(ex.ToString(), "Error");
            }

        }
    }
}
